/*
 * servertest.cc
 *
 *  Created on: Jun 29, 2011
 *      Author: peckb1
 */

#include "system.h"
#include "network.h"
#include "post.h"
#include "interrupt.h"
#include "bool.h"
#include "syscall.h"
#include "thread.h"


/* GLOBALS */
PacketHeader outPktHdr, inPktHdr;
MailHeader outMailHdr, inMailHdr;
char mailBuffer[MaxMailSize];
char data[MaxMailSize];
bool success;

int BAD_VALUE = -99999;

/* END GLOBALS */

/* SERVER HELPER CALLS */
void
Success(bool good) {
    if ( !good ) {
        printf("The postOffice Send failed. You must not have the other Nachos running. Terminating Nachos.\n");
        interrupt->Halt();
    }
}

int
CreateIntMVHelper(char* name, int size, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%s,%i", SC_CreateIntMV, name, size);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // we have been signaled sucsessfully
            token = strtok(NULL, ",");
            if(token) {
                return atoi(token);
            } else {
                return -1;
            }
        } else {
            printf("ERROR: I got a response but didn't make the Int MV.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return -1;
}


int
AlterIntMV(int mvKey, int index, int newValue, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i,%i,%i", SC_AlterIntMV, mvKey, index, newValue);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // we have been signaled sucsessfully
            token = strtok(NULL, ",");
            if(token) {
                return atoi(token);
            } else {
                return -1;
            }
        } else {
            printf("ERROR: I got a response but didn't make the Int MV Change.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return -1;
}

int
DestroyIntMV(int mvKey, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i", SC_DestroyIntMV, mvKey);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // we have been signaled sucsessfully
            token = strtok(NULL, ",");
            if(token) {
                return atoi(token);
            } else {
                return -1;
            }
        } else {
            printf("ERROR: I got a response but didn't make the Int MV Change.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return -1;
}


int
RetreiveIntMV(int mvKey, int index, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i,%i", SC_RetrieveIntMV, mvKey, index);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // we have been signaled sucsessfully
            token = strtok(NULL, ",");
            if(token) {
                return atoi(token);
            } else {
                return BAD_VALUE;
            }
        } else {
            printf("ERROR: I got a response but didn't make the Int MV Change.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return BAD_VALUE;
}


void
WaitServerLock(int cvId, int lockId, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i,%i", SC_Wait, cvId, lockId);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // we have been signaled sucsessfully
        } else {
            printf("ERROR: I got a response but don't have the lock.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return;
}

void
SignalServerLock(int cvId, int lockId, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i,%i", SC_Signal, cvId, lockId);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // we signaled sucsessfully
        } else {
            printf("ERROR: I got a response but did not signal properly.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return;
}

void
BroadcastServerLock(int cvId, int lockId, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i,%i", SC_Broadcast, cvId, lockId);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // we Broadcasted sucsessfully
        } else {
            printf("ERROR: I got a response but did not broadcast properly.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return;
}

void
ReleaseServerLock(int lockId, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i", SC_Release, lockId);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            token = strtok(NULL, ",");
            if(token) {
                // happy case
            }
        } else {
            printf("ERROR: I got a response but did not Release the Lock.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return;

}


void
AcquireServerLock(int lockId, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i", SC_Acquire, lockId);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            token = strtok(NULL, ",");
            if(token) {
                // happy case
            }
        } else {
            printf("ERROR: I got a response but don't have the lock.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return;

}

int
CreateServerCV(char* name, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%s", SC_CreateCV, name);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            token = strtok(NULL, ",");
            if(token) {
                return atoi(token);
            } else {
                return -1;
            }
        } else {
            printf("ERROR: I got a response but didn't Create the CV.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return -1;
}

void
DestroyServerLock(int lockId, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i", SC_DestroyLock, lockId);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // happy case
        } else {
            printf("ERROR: I got a response but didn't Destroy the lock.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return;
}

void
DestroyServerCV(int cvId, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%i", SC_DestroyCV, cvId);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            // happy case
        } else {
            printf("ERROR: I got a response but didn't Destroy the CV.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return;
}

int
CreateServerLock(char* name, int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    sprintf(data, "%i,%s", SC_CreateLock, name);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
    char* token = strtok(mailBuffer, ",");
    if(token != NULL) {
        if(atoi(token) == 1) {
            token = strtok(NULL, ",");
            if(token) {
                return atoi(token);
            } else {
                return -1;
            }
        } else {
            printf("ERROR: I got a response but didn't Create the lock.\n");
        }
    } else {
        printf("ERROR: Token was null.\n");
    }

    return -1;
}

/* END SERVER HELPER CALLS */

void
FirstTest(int serverMachineId, int serverId, int myMailBox) {
    // construct packet, mail header for original message
    // To: destination machine, mailbox 0
    // From: our machine, reply to: mailbox 1
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    // SC_CreateLock 11
    sprintf(data, "%i,%s", SC_CreateLock, "Create This Lock");
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_CreateCV 12
    sprintf(data, "%i,%s", SC_CreateCV, "Create This CV");
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_Acquire  13
    sprintf(data, "%i,%i", SC_Acquire, 2);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_Release  14
    sprintf(data, "%i,%i", SC_Release, 2);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_Wait     15
    sprintf(data, "%i,%i,%i", SC_Wait, 2, 4);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_Signal   16
    sprintf(data, "%i,%i,%i", SC_Signal, 2, 4);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_Broadcast 17
    sprintf(data, "%i,%i,%i", SC_Broadcast, 2, 4);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_DestroyLock 18
    sprintf(data, "%i,%i", SC_DestroyLock, 2);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);

    // SC_DestroyCV 19
    sprintf(data, "%i,%i", SC_DestroyCV, 4);
    outMailHdr.length = strlen(data) + 1;

    success = postOffice->Send(outPktHdr, outMailHdr, data);
    Success(success);
}

void
SecondTest(int serverMachineId, int serverId, int myMailBox) {
    // construct packet, mail header for original message
    // To: destination machine, mailbox 0
    // From: our machine, reply to: mailbox 1
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    // SC_CreateLock 11
    for(int i = 0; i < 10; i++) {
        int lockId = CreateServerLock("Test Lock", serverMachineId, serverId, myMailBox);
        printf("Lock that was create had ID %i.\n", lockId);
    }


    // SC_Acquire  13
    for(int i = 0; i < 10; i++) {
        sprintf(data, "%i,%i", SC_Acquire, i);
        outMailHdr.length = strlen(data) + 1;

        success = postOffice->Send(outPktHdr, outMailHdr, data);
        Success(success);

        postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
        char* token = strtok(mailBuffer, ",");
        if(token != NULL) {
            if(atoi(token) == 1) {
                token = strtok(NULL, ",");
                if(token) {
                    printf("I now own Lock #%i.\n", atoi(token));
                }
            } else {
                printf("ERROR: I got a response but don't have the lock.\n");
            }
        }
    }

    // SC_Release  14
    for(int i = 0; i < 10; i++) {
        sprintf(data, "%i,%i", SC_Release, i);
        outMailHdr.length = strlen(data) + 1;

        success = postOffice->Send(outPktHdr, outMailHdr, data);
        Success(success);

        postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
        char* token = strtok(mailBuffer, ",");
        if(token != NULL) {
            if(atoi(token) == 1) {
                token = strtok(NULL, ",");
                if(token) {
                    printf("I Released Lock# #%i.\n", atoi(token));
                }
            } else {
                printf("ERROR: I got a response but didn't release the lock.\n");
            }
        }
    }

    // SC_DestroyLock 18
    for(int i = 0; i < 10; i++) {
         sprintf(data, "%i,%i", SC_DestroyLock, i);
         outMailHdr.length = strlen(data) + 1;

         success = postOffice->Send(outPktHdr, outMailHdr, data);
         Success(success);

         postOffice->Receive(myMailBox, &inPktHdr, &inMailHdr, mailBuffer);
         char* token = strtok(mailBuffer, ",");
         if(token != NULL) {
             if(atoi(token) == 1) {
                 token = strtok(NULL, ",");
                 if(token) {
                     printf("I Destroyed Lock# #%i.\n", atoi(token));
                 }
             } else {
                 printf("ERROR: I got a response but didn't Destroy the lock.\n");
             }
         }
     }

}

int thirdTestLockId;
int thirdTestCVId;

int thirdTestMachineId;
int thirdTestServerId;
int thirdTestMailBoxId;


void
ThirdTestWakingThread() {
    int myMailBox = thirdTestMailBoxId++;

    AcquireServerLock(thirdTestLockId, thirdTestMachineId, thirdTestServerId, myMailBox);

    SignalServerLock(thirdTestCVId, thirdTestLockId, thirdTestMachineId, thirdTestServerId, myMailBox);

    ReleaseServerLock(thirdTestLockId, thirdTestMachineId, thirdTestServerId, myMailBox);
    Exit(0);
}

void
ThirdTest(int serverMachineId, int serverId, int myMailBox) {
    thirdTestMachineId = serverMachineId;
    thirdTestServerId = serverId;
    thirdTestMailBoxId = myMailBox;

    thirdTestLockId = CreateServerLock("Third Lock", serverMachineId, serverId, myMailBox);
    thirdTestCVId = CreateServerCV("Third CV", serverMachineId, serverId, myMailBox);

    if(thirdTestLockId == -1 || thirdTestCVId == -1) {
        printf("Unable to create Lock/CV.\n");
        return;
    }

    AcquireServerLock(thirdTestLockId, serverMachineId, serverId, myMailBox);

    Thread* t = new Thread("ThirdTestWakingThread");
    t->Fork((VoidFunctionPtr)ThirdTestWakingThread, 0);
    WaitServerLock(thirdTestCVId, thirdTestLockId, serverMachineId, serverId, myMailBox);

    ReleaseServerLock(thirdTestLockId, serverMachineId, serverId, myMailBox);

    DestroyServerLock(thirdTestLockId, serverMachineId, serverId, myMailBox);

    DestroyServerCV(thirdTestCVId, serverMachineId, serverId, myMailBox);

    Exit(0);
}

int fourthTestLockId;
int fourthTestCVId;

int fourthTestMachineId;
int fourthTestServerId;
int fourthTestMailBoxId;

int counter = 0;

void
FourthTestWaitingThread() {
    int myMailBox = ++fourthTestMailBoxId;

    counter++;

    printf("Box %i calling Acquire.\n", myMailBox);
    AcquireServerLock(fourthTestLockId, fourthTestMachineId, fourthTestServerId, myMailBox);

    printf("Box %i calling Release.\n", myMailBox);
    ReleaseServerLock(fourthTestLockId, fourthTestMachineId, fourthTestServerId, myMailBox);

    printf("Box %i finished Acquire/Release.\n", myMailBox);
    counter --;
}

void
FourthTest(int serverMachineId, int serverId, int myMailBox) {
    fourthTestMachineId = serverMachineId;
    fourthTestServerId = serverId;
    fourthTestMailBoxId = myMailBox;

    fourthTestLockId = CreateServerLock("Fourth Lock", serverMachineId, serverId, myMailBox);
    fourthTestCVId = CreateServerCV("Fourth CV", serverMachineId, serverId, myMailBox);

    if(fourthTestLockId == -1 || fourthTestCVId == -1) {
        printf("Unable to create Lock/CV.\n");
        return;
    }

    AcquireServerLock(fourthTestLockId, serverMachineId, serverId, myMailBox);
    Thread* t = new Thread("FourthTestWaitingThread");
    t->Fork((VoidFunctionPtr)FourthTestWaitingThread, 0);

    t = new Thread("FourthTestWaitingThread");
    t->Fork((VoidFunctionPtr)FourthTestWaitingThread, 0);

    t = new Thread("FourthTestWaitingThread");
    t->Fork((VoidFunctionPtr)FourthTestWaitingThread, 0);

    t = new Thread("FourthTestWaitingThread");
    t->Fork((VoidFunctionPtr)FourthTestWaitingThread, 0);

    t = new Thread("FourthTestWaitingThread");
    t->Fork((VoidFunctionPtr)FourthTestWaitingThread, 0);

    while(counter < 5) {
        currentThread->Yield();
    }


    BroadcastServerLock(fourthTestCVId, fourthTestLockId, serverMachineId, serverId, myMailBox);

    ReleaseServerLock(fourthTestLockId, serverMachineId, serverId, myMailBox);

    DestroyServerLock(fourthTestLockId, serverMachineId, serverId, myMailBox);

    DestroyServerCV(fourthTestCVId, serverMachineId, serverId, myMailBox);

    while(counter > 0) {
        currentThread->Yield();
    }
}

void
SixthTest(int serverMachineId, int serverId, int myMailBox) {
    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId; // server's mailbox
    outMailHdr.from = myMailBox; // my mailbox

    // gonna send some bad data
    sprintf(data, "%i,%i", SC_Acquire, 0);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i", SC_Release, -1);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i", SC_DestroyLock, 10);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i", SC_DestroyCV, 2);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i,%i", SC_Wait, 0, 0);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i,%i", SC_Signal, 30, -1);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i,%i", SC_Broadcast, 0, 14);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);
}

int seventhTestLockId;
int seventhTestCVId;

int seventhTestMachineId;
int seventhTestServerId;
int seventhTestMailBoxId;

void
SeventhTestHelperThread() {

    int myMailBox = ++seventhTestMailBoxId;

    seventhTestCVId = CreateServerCV("Seventh CV", seventhTestMachineId, seventhTestServerId, myMailBox);

    sprintf(data, "%i,%i", SC_Acquire, seventhTestLockId);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i,%i", SC_Wait, seventhTestCVId, seventhTestLockId);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    counter++;

    while(counter > 0) {
        currentThread->Yield();
    }

    sprintf(data, "%i,%i", SC_Acquire, seventhTestLockId);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    sprintf(data, "%i,%i,%i", SC_Wait, seventhTestCVId, seventhTestLockId);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    counter++;

    DestroyServerCV(seventhTestCVId, seventhTestMachineId, seventhTestServerId, myMailBox);
}

void
SeventhTest(int serverMachineId, int serverId, int myMailBox) {
    seventhTestMachineId = serverMachineId;
    seventhTestServerId = serverId;
    seventhTestMailBoxId = myMailBox;
    counter = 0;

    seventhTestLockId = CreateServerLock("Seventh Lock", serverMachineId, serverId, myMailBox);

    AcquireServerLock(seventhTestLockId, serverMachineId, serverId, myMailBox);

    DestroyServerLock(seventhTestLockId, serverMachineId, serverId, myMailBox);

    Thread* t = new Thread("SeventhTestHelperThread");
    t->Fork((VoidFunctionPtr)SeventhTestHelperThread, 0);

    while(counter == 0) {
        currentThread->Yield();
    }

    ReleaseServerLock(seventhTestLockId, serverMachineId, serverId, myMailBox);

    counter--;
    while(counter == 0) {
        currentThread->Yield();
    }
}

int eighthTestLockId;
int eighthTestCVId;

int eighthTestMachineId;
int eighthTestServerId;
int eighthTestMailBoxId;

void
EighthTestHelperThread() {

    int myMailBox = ++eighthTestMailBoxId;

    DestroyServerCV(eighthTestCVId, eighthTestMachineId, eighthTestServerId, myMailBox);

    AcquireServerLock(eighthTestLockId, eighthTestMachineId, eighthTestServerId, myMailBox);

    sprintf(data, "%i,%i,%i", SC_Wait, eighthTestCVId, eighthTestLockId);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    DestroyServerLock(eighthTestLockId, eighthTestMachineId, eighthTestServerId, myMailBox);

    sprintf(data, "%i,%i,%i", SC_Wait, eighthTestCVId, eighthTestLockId);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);

    SignalServerLock(eighthTestCVId, eighthTestLockId, eighthTestMachineId, eighthTestServerId, myMailBox);

    ReleaseServerLock(eighthTestLockId, eighthTestMachineId, eighthTestServerId, myMailBox);
}

void
EighthTest(int serverMachineId, int serverId, int myMailBox) {
    eighthTestMachineId = serverMachineId;
    eighthTestServerId = serverId;
    eighthTestMailBoxId = myMailBox;

    eighthTestLockId = CreateServerLock("Eighth Lock", serverMachineId, serverId, myMailBox);
    eighthTestCVId = CreateServerCV("Eighth CV", serverMachineId, serverId, myMailBox);

    AcquireServerLock(eighthTestLockId, serverMachineId, serverId, myMailBox);

    Thread* t = new Thread("EighthTestHelperThread");
    t->Fork((VoidFunctionPtr)EighthTestHelperThread, 0);

    WaitServerLock(eighthTestCVId, eighthTestLockId, serverMachineId, serverId, myMailBox);

    ReleaseServerLock(eighthTestLockId, serverMachineId, serverId, myMailBox);
}

void
NinthTest(int serverMachineId, int serverId, int myMailBox) {

    for(int i = 0; i < 100; i++) {
        CreateServerLock("Lock Name", serverMachineId, serverId, myMailBox);
    }

    for(int i = 90; i < 100; i++) {
        sprintf(data, "%i,%i", SC_Acquire, i);
        outMailHdr.length = strlen(data) + 1;
        postOffice->Send(outPktHdr, outMailHdr, data);
    }

    for(int i = 90; i < 100; i++) {
        sprintf(data, "%i,%i", SC_Release, i);
        outMailHdr.length = strlen(data) + 1;
        postOffice->Send(outPktHdr, outMailHdr, data);
    }
}

void TenthTest(char* name, int size, int serverMachineId, int serverId, int myMailBox) {
    int val = rand()%45 + 1;
    int newVal = rand()%963 + 1;
    int index = rand()%size;

    printf("Creating IntArray MV (%s) with size %i.\n", name, size);
    int mvKey = CreateIntMVHelper(name, size, serverMachineId, serverId, myMailBox);

    printf("Got index: %i for name %s.\n", mvKey, name);

    AlterIntMV(mvKey, index, val, serverMachineId, serverId, myMailBox);

    int currentMVValue = RetreiveIntMV(mvKey, index, serverMachineId, serverId, myMailBox);

    printf("Sent '%i' to be saved. '%i' is currently being stored.\n", val, currentMVValue);

    AlterIntMV(mvKey, index, newVal, serverMachineId, serverId, myMailBox);

    currentMVValue = RetreiveIntMV(mvKey, index, serverMachineId, serverId, myMailBox);

    printf("Sent '%i' to be Altered. '%i' is currently being stored.\n", newVal, currentMVValue);
}

void TenthTestHelper(int serverMachineId, int serverId, int myMailBox) {
    int firstLockSize  = rand()%10 + 1;
    int secondLockSize = rand()%10 + 1;

    TenthTest("First Lock" , firstLockSize , serverMachineId, serverId, myMailBox);
    TenthTest("Second Lock", secondLockSize, serverMachineId, serverId, myMailBox);
    TenthTest("First Lock" , firstLockSize , serverMachineId, serverId, myMailBox);
    TenthTest("Second Lock", secondLockSize, serverMachineId, serverId, myMailBox);
    TenthTest("First Lock" , firstLockSize , serverMachineId, serverId, myMailBox);
}

void EleventhTest(int serverMachineId, int serverId, int myMailBox) {
    char* name = "Lock Eleven 1";
    char* nameTwo = "Lock Eleven 2";

    int eleventhLockId = CreateServerLock(name, serverMachineId, serverId, myMailBox);

    int nextLockId = -1;

    nextLockId = CreateServerLock(name, serverMachineId, serverId, myMailBox);

    printf("\n%i: Original Lock ID \n%i: Returned Lock ID after creating with the same name.\n", eleventhLockId, nextLockId);

    eleventhLockId = -1;
    nextLockId = -1;
    eleventhLockId = CreateServerLock(name, serverMachineId, serverId, myMailBox);
    nextLockId = CreateServerLock(name, serverMachineId, serverId, myMailBox);
    printf("\n%i: Returned Lock ID after creating with the same name.\n%i: Returned Lock ID after creating with the same name.\n", eleventhLockId, nextLockId);

    eleventhLockId = -1;
    nextLockId = -1;
    eleventhLockId = CreateServerLock(nameTwo, serverMachineId, serverId, myMailBox);
    nextLockId = CreateServerLock(nameTwo, serverMachineId, serverId, myMailBox);
    printf("\n%i: Original Lock ID \n%i: Returned Lock ID after creating with the same name.\n", eleventhLockId, nextLockId);

    eleventhLockId = -1;
    nextLockId = -1;
    eleventhLockId = CreateServerLock(nameTwo, serverMachineId, serverId, myMailBox);
    nextLockId = CreateServerLock(nameTwo, serverMachineId, serverId, myMailBox);
    printf("\n%i: Returned Lock ID after creating with the same name.\n%i: Returned Lock ID after creating with the same name.\n", eleventhLockId, nextLockId);
}

void TwelfthTest(int serverMachineId, int serverId, int myMailBox) {
    char* name = "CV Eleven 1";
    char* nameTwo = "CV Eleven 2";

    int eleventhCVId = CreateServerCV(name, serverMachineId, serverId, myMailBox);

    int nextCVId = -1;

    nextCVId = CreateServerCV(name, serverMachineId, serverId, myMailBox);

    printf("\n%i: Original CV ID \n%i: Returned Lock CV after creating with the same name.\n", eleventhCVId, nextCVId);

    eleventhCVId = -1;
    nextCVId = -1;
    eleventhCVId = CreateServerCV(name, serverMachineId, serverId, myMailBox);
    nextCVId = CreateServerCV(name, serverMachineId, serverId, myMailBox);
    printf("\n%i: Returned CV ID after creating with the same name.\n%i: Returned CV ID after creating with the same name.\n", eleventhCVId, nextCVId);

    eleventhCVId = -1;
    nextCVId = -1;
    eleventhCVId = CreateServerCV(nameTwo, serverMachineId, serverId, myMailBox);
    nextCVId = CreateServerCV(nameTwo, serverMachineId, serverId, myMailBox);
    printf("\n%i: Original CV ID \n%i: Returned CV ID after creating with the same name.\n", eleventhCVId, nextCVId);

    eleventhCVId = -1;
    nextCVId = -1;
    eleventhCVId = CreateServerCV(nameTwo, serverMachineId, serverId, myMailBox);
    nextCVId = CreateServerCV(nameTwo, serverMachineId, serverId, myMailBox);
    printf("\n%i: Returned CV ID after creating with the same name.\n%i: Returned CV ID after creating with the same name.\n", eleventhCVId, nextCVId);
}

void ThirtenthTest(int serverMachineId, int serverId, int myMailBox) {
    printf("Creating Lock to use.\n");
    int lockId = CreateServerLock("Create This Lock", serverMachineId, serverId, myMailBox);

    printf("Got Lock ID: %i.\n", lockId);

    printf("Calling Acquire.\n");
    AcquireServerLock(lockId, serverMachineId+1, serverId, myMailBox);

    printf("Calling Release.\n");
    ReleaseServerLock(lockId, serverMachineId, serverId, myMailBox);

    printf("Calling Delete.\n");
    DestroyServerLock(lockId, serverMachineId+1, serverId, myMailBox);

    outPktHdr.to = serverMachineId; //servers machine ID
    outMailHdr.to = serverId;       // server's mailbox
    outMailHdr.from = myMailBox;    // my mailbox
    printf("Calling Acquire again - server should yell an error.\n");
    sprintf(data, "%i,%i", SC_Acquire, lockId);
    outMailHdr.length = strlen(data) + 1;
    postOffice->Send(outPktHdr, outMailHdr, data);
}


int fourteenthTestLockId;
int fourteenthTestCVId;

int fourteenthTestMachineId;
int fourteenthTestServerId;
int fourteenthTestMailBoxId;

void FourteenthTestHelper() {
    int myMailBox = currentThread->getID();//++fourteenthTestMailBoxId;
    int serverMachine = rand()%2;

    counter++;

    printf("Helper: Counter is: %i.\n", counter);
    printf("Box %i calling Acquire to Machine %i.\n", myMailBox, serverMachine);
    AcquireServerLock(fourthTestLockId, serverMachine, fourthTestServerId, myMailBox);

    counter++;
    printf("Helper: Counter is: %i.\n", counter);
    serverMachine = rand()%2;
    printf("Box %i calling Wait to Machine %i.\n", myMailBox, serverMachine);
    WaitServerLock(fourteenthTestCVId, fourteenthTestLockId, serverMachine, fourteenthTestServerId, myMailBox);

    serverMachine = rand()%2;
    printf("Box %i calling Release to Machine %i.\n", myMailBox, serverMachine);
    ReleaseServerLock(fourthTestLockId, serverMachine, fourthTestServerId, myMailBox);

    printf("Box %i finished Acquire/Release.\n", myMailBox);
    counter --;
}

void FourteenthTest(int serverMachineId, int serverId) {
    counter = 0;

    int myMailBox = currentThread->getID();

    fourteenthTestMachineId = serverMachineId;
    fourteenthTestServerId  = serverId;
    fourteenthTestMailBoxId = myMailBox;

    fourteenthTestLockId = CreateServerLock("Fourteenth Lock", fourteenthTestServerId, fourteenthTestServerId, myMailBox);
    fourteenthTestCVId   = CreateServerCV("Fourteenth CV", fourteenthTestServerId+1, fourteenthTestServerId, myMailBox);

    if(fourteenthTestLockId == -1 || fourteenthTestCVId == -1) {
        printf("Unable to create Lock/CV.\n");
        return;
    }

    AcquireServerLock(fourteenthTestLockId, serverMachineId, fourteenthTestServerId, myMailBox);
    Thread* t = new Thread("FourteenthTestHelper");
    t->Fork((VoidFunctionPtr)FourteenthTestHelper, 0);


    t = new Thread("FourteenthTestHelper");
    t->Fork((VoidFunctionPtr)FourteenthTestHelper, 0);

    t = new Thread("FourteenthTestHelper");
    t->Fork((VoidFunctionPtr)FourteenthTestHelper, 0);

    t = new Thread("FourteenthTestHelper");
    t->Fork((VoidFunctionPtr)FourteenthTestHelper, 0);

    t = new Thread("FourteenthTestHelper");
    t->Fork((VoidFunctionPtr)FourteenthTestHelper, 0);


    printf("Main: Counter is: %i.\n", counter);
    while(counter < 5) {
        currentThread->Yield();
    }

    counter = 0;
    ReleaseServerLock(fourteenthTestLockId, fourteenthTestMachineId+1, fourteenthTestServerId, myMailBox);

    printf("Main: Counter is: %i.\n", counter);
    while(counter < 5) {
        currentThread->Yield();
    }

    for(int i = 0; i < 10; i++) {
        currentThread->Yield();
    }

    printf("Calling Signal.\n");
    SignalServerLock(fourteenthTestCVId, fourteenthTestLockId, fourteenthTestMachineId, fourteenthTestServerId, myMailBox);

    for(int i = 0; i < 10; i++) {
        currentThread->Yield();
    }
    while(counter >= 5) {
        currentThread->Yield();
    }
    for(int i = 0; i < 10; i++) {
        currentThread->Yield();
    }

    printf("Calling Broadcast.\n");
    BroadcastServerLock(fourteenthTestCVId, fourteenthTestLockId, fourteenthTestMachineId, fourteenthTestServerId, myMailBox);

    while(counter > 0) {
        currentThread->Yield();
    }

    DestroyServerLock(fourteenthTestLockId, fourteenthTestMachineId, fourteenthTestServerId, myMailBox);

    DestroyServerCV(fourteenthTestCVId, fourteenthTestMachineId+1, fourteenthTestServerId, myMailBox);

}

void FifteenthTest(int serverMachineId, int serverId, int myMailBox) {
    printf("Creating a MV with Server 0.\n");
    int mvIndex = CreateIntMVHelper("Some Data", 5, serverMachineId, serverId, myMailBox);

    printf("Setting data (42) with Server 1.\n");
    AlterIntMV(mvIndex, 2, 42, serverMachineId+1, serverId, myMailBox);

    printf("Retrieving the data with Server 0.\n");
    int dataReturned = RetreiveIntMV(mvIndex, 2, serverMachineId, serverId, myMailBox);
    printf("Server told us that the value was: %i.\n", dataReturned);

    printf("Deleting the data with Server 1.\n");
    DestroyIntMV(mvIndex, serverMachineId+1, serverId, myMailBox);

}


void
ServerTester(int serverMachineId, int serverId, int myMailBox, int testNumber) {

    if(testNumber == 1) {
        SixthTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 2) {
        NinthTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 3) {
        ThirdTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 4) {
        FourthTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 5) {
        FirstTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 6) {
        SecondTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 7) {
        SeventhTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 8) {
        EighthTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 9) {
        TenthTestHelper(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 10) {
        EleventhTest(serverMachineId, serverId, myMailBox);
    } else if(testNumber == 11) {
        TwelfthTest(serverMachineId, serverId, myMailBox);
    }
    #ifdef NETWORK
        else if(testNumber == 12) {
            ThirtenthTest(serverMachineId, serverId, currentThread->getID());
        } else if(testNumber == 13) {
            FourteenthTest(serverMachineId, serverId);
        } else if(testNumber == 14) {
            FifteenthTest(serverMachineId, serverId, currentThread->getID());
        }
    #endif

    interrupt->Halt();
}
